package com.ctshk.rpc.order.hotel.service.impl;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.constant.CurrencyRateExchangeConstant;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.*;
import com.ctshk.common.enums.hotel.HotelOrdersType;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.utils.DateUtil;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.NumberUtil;
import com.ctshk.common.utils.SnowflakeIdWorker;
import com.ctshk.rpc.booking.enums.SupplierReserveTypeEnum;
import com.ctshk.rpc.booking.req.system.hotel.add.SupplierOrderSystemHotelAddReq;
import com.ctshk.rpc.booking.req.system.hotel.add.SupplierSystemOrderHotelCheckInAddReq;
import com.ctshk.rpc.booking.service.ISupplierOrderService;
import com.ctshk.rpc.hotel.req.HotelManualOrderReq;
import com.ctshk.rpc.hotel.service.IHotelManualOrderService;
import com.ctshk.rpc.order.hotel.entity.HotelManualOrder;
import com.ctshk.rpc.order.hotel.entity.HotelOrder;
import com.ctshk.rpc.order.hotel.mapper.HotelManualOrderMapper;
import com.ctshk.rpc.order.hotel.mapper.HotelOrderMapper;
import com.ctshk.rpc.order.hotel.mapper.HotelOrderTouristMapper;
import com.ctshk.rpc.system.dto.SysDepartmentDTO;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.service.IMainDataCurrencyService;
import com.ctshk.rpc.system.service.IMainDataManualSystemService;
import com.ctshk.rpc.system.service.ISysDepartmentService;
import com.ctshk.rpc.system.service.ISysUserService;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * <p>
 * 酒店手工单（外挂单） 服务实现类
 * </p>
 *
 * @author yinhuan
 * @since 2021-03-08
 */
@Slf4j
@DubboService
public class HotelManualOrderServiceImpl extends ServiceImpl<HotelManualOrderMapper, HotelManualOrder> implements IHotelManualOrderService {
    @Autowired
    private HotelManualOrderMapper hotelManualOrderMapper;
    @Autowired
    private HotelOrderTouristMapper hotelOrderTouristMapper;
    @Autowired
    private HotelOrderMapper hotelOrderMapper;

    @DubboReference
    private ISysUserService sysUserService;
    @DubboReference
    private ISysDepartmentService sysDepartmentService;
    @DubboReference
    private IMainDataCurrencyService mainDataCurrencyService;
    @DubboReference
    private ISupplierOrderService supplierOrderService;
    @DubboReference
    private IMainDataManualSystemService mainDataManualSystemService;

    /**
     * 添加外挂单
     * @param req
     * @param userId
     */
    @Override
    // @GlobalTransactional
    @Transactional
    public Long addHotelManualOrder(HotelManualOrderReq req, Long userId) {

        // 先添加订单
        UserDTO userDTO = sysUserService.loadUserByParam(userId, 1);
        String employeeNumber = userDTO.getEmployeeNumber();
        SysDepartmentDTO sysDepartmentDTO = sysDepartmentService.queryOne(userDTO.getDeptId());
        String deptCode = sysDepartmentDTO.getDeptCode();
        LocalDateTime now = LocalDateTime.now();

        HotelOrder hotelOrder = new HotelOrder();
        Long orderId = SnowflakeIdWorker.nextId();
        String orderNumber = NumberUtil.generatorOrderHotelNumber(deptCode, employeeNumber);
        hotelOrder.setId(orderId);
        hotelOrder.setOrderNumber(orderNumber);
        hotelOrder.setOrdersType(HotelOrdersType.AGENT.getCode());
        hotelOrder.setCostCurrencyId(req.getCurrencyId());
        hotelOrder.setCostCurrencyName(req.getCurrencyName());
        hotelOrder.setCostExchangeRate(req.getExchangeRate());
        hotelOrder.setCheckInDate(req.getCheckInDate());
        hotelOrder.setCheckOutDate(req.getCheckOutDate());
        hotelOrder.setNumber(req.getRoomNumber());
        hotelOrder.setPaymentStatus(OrderPaymentStatus.UN_PAYMENT.getCode());
        hotelOrder.setScheduledStatus(null);
        hotelOrder.setCancelStatus(null);
        hotelOrder.setSalesmanId(userId);
        hotelOrder.setSalesmanName(userDTO.getFullName());
        hotelOrder.setSurname(req.getHotelOrderContactPersonInfo().getContactSurname());
        hotelOrder.setName(req.getHotelOrderContactPersonInfo().getContactName());
        hotelOrder.setContactName(StrUtil.concat(true, req.getHotelOrderContactPersonInfo().getContactSurname(), req.getHotelOrderContactPersonInfo().getContactName()));
        hotelOrder.setContactMobile(req.getHotelOrderContactPersonInfo().getContactMobile());
        hotelOrder.setContactMobileAreaCodeId(req.getHotelOrderContactPersonInfo().getContactMobileAreaCodeId());
        hotelOrder.setContactMobileAreaCode(req.getHotelOrderContactPersonInfo().getContactMobileAreaCode());
        hotelOrder.setContactCountryId(req.getHotelOrderContactPersonInfo().getContactCountryId());
        hotelOrder.setContactCountryName(req.getHotelOrderContactPersonInfo().getContactCountryName());
        hotelOrder.setContactAppellation(req.getHotelOrderContactPersonInfo().getContactAppellation());
        hotelOrder.setContactEmail(req.getHotelOrderContactPersonInfo().getContactEmail());
        hotelOrder.setNights(req.getNights());
        hotelOrder.setPayExpireDate(LocalDateTime.now().plusMinutes(30));
        hotelOrder.setRemark(req.getRemark());
        hotelOrder.setCreateId(userId);
        hotelOrder.setIsDeleted(0);
        BigDecimal costPriceHkd = mainDataCurrencyService.getHkdAmountByType(req.getCurrencyId(), CurrencyRateExchangeConstant.PLANNED_EXCHANGE_RATE_, req.getCostPrice());
        BigDecimal receivableAmount = costPriceHkd.add(req.getReserveCharge()).multiply(new BigDecimal(req.getRoomNumber())).multiply(new BigDecimal(req.getNights()));
        hotelOrder.setOrderAmount(receivableAmount);
        hotelOrder.setReceivableAmount(receivableAmount);
        hotelOrder.setRefundedAmount(new BigDecimal(0));
        hotelOrder.setCityName(req.getCityName());
        hotelOrder.setBrandName(req.getHotelName());
        hotelOrder.setHotelName(req.getHotelName());
        hotelOrder.setRoomName(req.getRoomName());
        hotelOrder.setHasBreakfast(req.getHasBreakfast());
        hotelOrder.setIsManual(1);
        hotelOrder.setSource(OrderSource.CPM.getCode());
        hotelOrder.setGmtCreate(now);
        hotelOrder.setGmtModified(now);

        hotelOrderMapper.insert(hotelOrder);

        // 再添加外挂单信息
        HotelManualOrder hotelManualOrder = EntityUtil.copy(req, HotelManualOrder.class);
        Long manualId = SnowflakeIdWorker.nextId();
        hotelManualOrder.setId(manualId);
        hotelManualOrder.setOrderId(orderId);
        hotelManualOrder.setGmtCreate(now);
        hotelManualOrder.setGmtModified(now);
        hotelManualOrderMapper.insert(hotelManualOrder);

        // 生成供应商预订单
        generatorSupplierBooking(hotelOrder, hotelManualOrder, userId, now);

        return manualId;
    }

    private void generatorSupplierBooking(HotelOrder hotelOrder, HotelManualOrder hotelManualOrder, Long userId, LocalDateTime localDateTime) {
        SupplierOrderSystemHotelAddReq supplierOrderSystemHotelAddReq = new SupplierOrderSystemHotelAddReq();
        log.info("【酒店外挂单】生成供应商预订");
        // 生成供应预订单buildSupplier
        UserDTO chargeUser = sysUserService.queryCacheUser(userId);
        // 资源所属部门ID
        supplierOrderSystemHotelAddReq.setDepartmentId(chargeUser.getDeptId());
        supplierOrderSystemHotelAddReq.setDepartment(chargeUser.getDept());
        supplierOrderSystemHotelAddReq.setBusinessType(SystemBusinessType.HOTEL.getCode());
        supplierOrderSystemHotelAddReq.setReserveTypeId(SupplierReserveTypeEnum.HOTEL.getId());
        supplierOrderSystemHotelAddReq.setSaleType(SalesMethod.SINGLE_SALE.getCode());
        supplierOrderSystemHotelAddReq.setProductType(ProductType.API_PRODUCT.getCode());
        supplierOrderSystemHotelAddReq.setTotalFee(hotelOrder.getOrderAmount());
        supplierOrderSystemHotelAddReq.setPayableAmount(hotelOrder.getReceivableAmount());
        supplierOrderSystemHotelAddReq.setSaleNumber(hotelOrder.getOrderNumber());
        supplierOrderSystemHotelAddReq.setCurrencyId(hotelOrder.getCostCurrencyId());
        supplierOrderSystemHotelAddReq.setTicketMode(hotelManualOrder.getTicketMode());
        // 供应商ID
        Result supplier = mainDataManualSystemService.querySupplierIdById(hotelManualOrder.getSystemId());
        if (!supplier.isSuccess()) {
            SystemError result = SystemError.getDefined(supplier.getCode());
            throw new BusinessException(result);
        }
        supplierOrderSystemHotelAddReq.setSupplierId((Long) supplier.getData());
        // 供应商订单类型
        supplierOrderSystemHotelAddReq.setSupplierOrderType("1");
        // 供应商订单号(第三方单号)
        supplierOrderSystemHotelAddReq.setSupplierOrderNumber("");
        // 确认状态
        supplierOrderSystemHotelAddReq.setConfirmStatus(SupplierConfirmStatus.CONFIRMED.getCode());
        supplierOrderSystemHotelAddReq.setConfirmTime(localDateTime);

        // 构建供应商预订-酒店入住信息
        SupplierSystemOrderHotelCheckInAddReq supplierSystemOrderHotelCheckInAddReq = new SupplierSystemOrderHotelCheckInAddReq();
        supplierSystemOrderHotelCheckInAddReq.setHotelId(hotelManualOrder.getId());
        supplierSystemOrderHotelCheckInAddReq.setHotelName(hotelOrder.getHotelName());
        supplierSystemOrderHotelCheckInAddReq.setIncludeBreakfast(hotelManualOrder.getHasBreakfast());
        supplierSystemOrderHotelCheckInAddReq.setCheckInTime(DateUtil.toLocalDateTime(hotelOrder.getCheckInDate()));
        supplierSystemOrderHotelCheckInAddReq.setCheckOutTime(DateUtil.toLocalDateTime(hotelOrder.getCheckOutDate()));
        supplierSystemOrderHotelCheckInAddReq.setNum(hotelOrder.getNumber());
        supplierSystemOrderHotelCheckInAddReq.setNightNum(hotelOrder.getNights());
        // 房间单价-无需计算服务费和加幅
        supplierSystemOrderHotelCheckInAddReq.setPrice(hotelManualOrder.getCostPrice());
        // 小计-无需计算服务费和加幅
        supplierSystemOrderHotelCheckInAddReq.setTotalPrice(hotelManualOrder.getCostPrice().multiply(new BigDecimal(hotelManualOrder.getRoomNumber())));
        supplierSystemOrderHotelCheckInAddReq.setExtraService("");
        supplierSystemOrderHotelCheckInAddReq.setCustomerRemark(hotelOrder.getRemark());
        supplierSystemOrderHotelCheckInAddReq.setSupplierRemark(hotelOrder.getRemark());

        List<SupplierSystemOrderHotelCheckInAddReq> supplierSystemOrderHotelCheckInAddReqs = new ArrayList<>();
        supplierSystemOrderHotelCheckInAddReqs.add(supplierSystemOrderHotelCheckInAddReq);
        supplierOrderSystemHotelAddReq.setSupplierSystemOrderHotelCheckInAddReqList(supplierSystemOrderHotelCheckInAddReqs);
        supplierOrderService.addSystemHotel(supplierOrderSystemHotelAddReq, userId);
    }

}
